// @ts-ignore
import * as step from '@flow-step/step-toolkit'
import * as util from './util'
import process from "process";
import * as ossUpload from './oss-upload'
import {UploadInputs} from './upload-inputs'
import { v4 as uuidv4 } from 'uuid';
import * as redline from './redline'

const local_report_dir='trivy-image-scan-report'
const report_json='report.json'
const report_html='trivy-image-scan-report.html'
const FLOW_JOB_TOKEN: string = 'FLOW_JOB_TOKEN'
export const IS_LINUX = process.platform === 'linux';
export const IS_X64 = process.arch === 'x64';
export async function execute(){
    if(!IS_LINUX){
        step.error(`TrivyImageScan only supports Linux systems, Please use Linux`)
        process.exit(1);
    }
    if(!IS_X64){
        step.error(`TrivyImageScan only supports X64, Please use X64`)
        process.exit(1);
    }
    step.info(`Going to execute trivy image scan step`)
   // 如果 TARGET_PKG 是一个已定义的环境变量，那么你可以这样获取它的值：
    const targetPkgString = process.env['TARGET_PKG'];
    step.info("TARGET_PKG "+targetPkgString)
   // 请确保 TARGET_PKG 环境变量中的值是一个有效的 JSON 字符串。
   // 然后你可以尝试解析这个字符串并提取 DOCKER_URL 属性。
    let imageUrl: string | undefined;
    if (targetPkgString) {
        try {
            const targetPkg = JSON.parse(targetPkgString);
            imageUrl = targetPkg['DOCKER_URL'];
        } catch (error) {
            imageUrl = targetPkgString;
        }
    }
    step.info("DOCKER_URL is:"+imageUrl);
    if("serviceConnection" == process.env["authType"]){
        const flowJobToken: string | undefined =
            process.env[FLOW_JOB_TOKEN]

        if (flowJobToken == undefined) {
            let errMsg = 'missing FLOW_JOB_TOKEN';
            throw new Error(errMsg)
        }
        var serviceConnectionId = process.env["SERVICE_CONNECTION_ID"];
        var aliyunRegion = process.env["aliyunRegion"];
        var instance = process.env["instance"];

        // @ts-ignore
        var dockerAcrPersonalCertificate = await step.certificate.getDockerAcrEnterpriseCertificate(flowJobToken,serviceConnectionId,aliyunRegion,instance);
        if (dockerAcrPersonalCertificate == undefined || dockerAcrPersonalCertificate.username == undefined) {
            let errMsg = 'get docker user erro';
            throw new Error(errMsg)
        }

        step.exportEnvVar("TRIVY_USERNAME", dockerAcrPersonalCertificate.username)
        step.exportEnvVar("TRIVY_PASSWORD", dockerAcrPersonalCertificate.password)
    }else {
        const username: string | undefined = process.env["username"];
        const password: string | undefined = process.env["password"];

        // @ts-ignore
        step.exportEnvVar("TRIVY_USERNAME", username)
        // @ts-ignore
        step.exportEnvVar("TRIVY_PASSWORD", password)
    }


    // @ts-ignore
    step.info("try to scan image:"+imageUrl);

    if(imageUrl){
        const trivyPath = await util.installTrivy();

        await util.createDirectory(local_report_dir)
        const jsonFile = local_report_dir+util.SEP+report_json;
        
        // 检查是否启用在线模式
        const useOnlineMode = process.env['useOnlineMode'] === 'true';
        
        // 根据在线模式设置Trivy参数
        const skipDbUpdate = useOnlineMode ? [] : ['--skip-db-update'];
        const skipJavaDbUpdate = useOnlineMode ? [] : ['--skip-java-db-update'];
        const offlineScan = useOnlineMode ? [] : ['--offline-scan'];
        
        const trivyJsonCmd = `${trivyPath}${util.SEP}trivy image --exit-code 0 --cache-dir ${trivyPath} ${useOnlineMode ? '' : '--skip-db-update --skip-java-db-update --offline-scan'} -o ${jsonFile} -f json ${imageUrl}`;
        step.info(trivyJsonCmd)
        util.executeCmdSync(`${trivyPath}${util.SEP}trivy`,['image',
            '--exit-code', '0',
            '--cache-dir', trivyPath,
            ...skipDbUpdate,
            ...skipJavaDbUpdate,
            '--scanners', 'vuln',
            ...offlineScan,
            '-o', `${jsonFile}`,
            '-f', 'json',
            imageUrl])
        await util.summarizeVulnerabilities(jsonFile)
        
        // 为HTML报告生成也应用相同的在线模式逻辑
        const trivyHtmlCmd = `${trivyPath}${util.SEP}trivy image --exit-code 0 --cache-dir ${trivyPath} ${useOnlineMode ? '' : '--skip-db-update --skip-java-db-update --offline-scan'} --format template --template "@${trivyPath}${util.SEP}contrib${util.SEP}html.tpl" -o ${local_report_dir}${util.SEP}${report_html} ${imageUrl}`
        step.info(trivyHtmlCmd)
        util.executeCmdSync(`${trivyPath}${util.SEP}trivy`,['image',
            '--exit-code', '0',
            '--cache-dir', trivyPath,
            ...skipDbUpdate,
            ...skipJavaDbUpdate,
            '--format template',
            `--template "@${trivyPath}${util.SEP}contrib${util.SEP}html.tpl"`,
            ...offlineScan,
            '-o', `${local_report_dir}${util.SEP}${report_html}`,
            imageUrl])

        // 上传报告
        const uuid = uuidv4();

        let inputs = {} as unknown as UploadInputs

        inputs.artifactName = `${report_html}`
        inputs.bucketName = process.env['BUCKET_NAME']
        inputs.accessKeyId = process.env['ACCESS_KEY_ID']
        inputs.accessKeySecret = process.env['ACCESS_KEY_SECRET']
        inputs.token = process.env['SECURITY_TOKEN']
        inputs.artifactFullName=local_report_dir+util.SEP+report_html
        inputs.fileId = `${process.env['REGION_ID']}/${process.env['PIPELINE_ID']}/${uuid}/${report_html}`
        ossUpload.put(inputs)

        redline.reportResultUrl(`http://testing.rdc.aliyun.com/assets/${process.env['REGION_ID']}/${process.env['PIPELINE_ID']}/${uuid}/${report_html}`);

    }else{
        step.error("no docker image found ")
        process.exit(1)
    }
}